package com.padakeji.android.ui.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AbsListView;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ListAdapter;
import android.widget.AbsListView.OnScrollListener;

/**
 * Created by atanl on 15/3/14.
 */
public class PinnedHeaderListView extends ExpandableListView implements OnScrollListener {
	
	private final String TAG = this.getClass().getCanonicalName();
	
	private PinnedHeaderListAdapter mAdapter;

    private View mHeaderView;
    
    private int mHeaderMeasuredWidth;
    private int mHeaderMeasuredHeight;
    
    private int mHeaderOffset;

//    private boolean mHeaderViewVisible;
    
    private OnScrollListener mOnScrollListener;

    private int dividerHeight;
    
    /**
     * http://developer.android.com/training/custom-views/create-view.html
     * @param context
     */
    public PinnedHeaderListView(Context context) {
        super(context);
        init();
    }

    public PinnedHeaderListView(Context context, AttributeSet attrs) {
        super(context, attrs);
//        TypedArray a = context.getTheme().obtainStyledAttributes(
//                attrs,
//                R.styleable.PinnedHeaderListView,
//                0, 0);
//
//        try {
//            mShowText = a.getBoolean(R.styleable.PinnedHeaderListView_test1, false);
//        } finally {
//            a.recycle();
//        }
        
        init();
    }

    
    public PinnedHeaderListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
    
    
    private void init() {
    	dividerHeight = getDividerHeight();
    	super.setOnScrollListener(this);
    }

    
    /**
     * This overloaded method should not be used, instead use
     * {@link #setAdapter(PinnedHeaderListAdapter)}.
     * Or nothing will be done but throw runtime exception.
     * <p>
     * {@inheritDoc}
     */
    @Override
    public void setAdapter(ListAdapter adapter) {
        throw new RuntimeException(
                "For ExpandableListView, use setAdapter(PinnedHeadListAdapter) instead of " +
                "setAdapter(ListAdapter)");
    }
    
    /**
     * This overloaded method should not be used, instead use
     * {@link #setAdapter(PinnedHeaderListAdapter)}.
     * Or nothing will be done but throw runtime exception.
     * <p>
     * {@inheritDoc}
     */
    @Override
    public void setAdapter(ExpandableListAdapter adapter) {
    	throw new RuntimeException(
                "For PinnedHeadListView, use setAdapter(PinnedHeadListAdapter) instead of " +
                "setAdapter(ExpandableListAdapter)");
    }
    
    
    /**
     * Sets the adapter that provides data to this view.
     * @param adapter The adapter that provides data to this view.
     */
    public void setAdapter(PinnedHeaderListAdapter adapter) {
		this.mAdapter = adapter;
		super.setAdapter(adapter);
	}
    
    
    /**
     * This method should not be used, use {@link #getExpandableListAdapter()}.
     */
    @Override
    public ListAdapter getAdapter() {
        /*
         * The developer should never really call this method on an
         * ExpandableListView, so it would be nice to throw a RuntimeException,
         * but AdapterView calls this
         */
        return super.getAdapter();
    }
    
    public ExpandableListAdapter getExpandableListAdapter() {
        return super.getExpandableListAdapter();
    }
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    	super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
    
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if (mHeaderView != null) {
        	mHeaderView.layout(l, t, mHeaderView.getMeasuredWidth(), mHeaderView.getMeasuredHeight());
        }
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        if (mAdapter == null || mHeaderView == null) {
        	return;
        }
        int saveCount = canvas.save();
        canvas.translate(0, mHeaderOffset);
        canvas.clipRect(0, 0, mHeaderMeasuredWidth, mHeaderMeasuredHeight); // needed
        drawChild(canvas, mHeaderView, getDrawingTime());
        canvas.restoreToCount(saveCount);
        
    }

    
	@Override
	public void setOnScrollListener(OnScrollListener l) {
		mOnScrollListener = l;
	}
	
    
	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		if (mOnScrollListener != null) {
			mOnScrollListener.onScrollStateChanged(view, scrollState);
		}
	}


	@Override
	public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
		if (mOnScrollListener != null) {
			mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
		}
		
		long packedPosition = getExpandableListPosition(firstVisibleItem);
		int groupPosition = getPackedPositionGroup(packedPosition);
		int childPosition = getPackedPositionChild(packedPosition);
		
		if (groupPosition != -1 && childPosition == -1) {
			View group = getChildAt(0);
			mHeaderMeasuredWidth = group.getMeasuredWidth();
			mHeaderMeasuredHeight = group.getMeasuredHeight();
		}
		
		if (mAdapter == null || firstVisibleItem < getHeaderViewsCount()) {
			mHeaderView = null;
			return;
		}
		
	    mHeaderView = mAdapter.getGroupView(groupPosition, mAdapter.isGroupExpanded(groupPosition), null, this);
	    
	    int width = MeasureSpec.getSize(mHeaderMeasuredWidth);
	    int height = MeasureSpec.getSize(mHeaderMeasuredHeight);
	    int headerMeasureWidth = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
	    int headerMeasureHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
	    mHeaderView.measure(headerMeasureWidth, headerMeasureHeight);

	    
	    mHeaderOffset = 0;
	    
	    
	    int i;
	    for (i = firstVisibleItem + 1; i < firstVisibleItem + visibleItemCount; ++i) {
	    	long cursorPackedPosition = getExpandableListPosition(i);
		    int cursorGroupPosition = getPackedPositionGroup(cursorPackedPosition);
		    if (cursorGroupPosition != groupPosition) {
		    	View cursorGroupView = getChildAt(i - firstVisibleItem);
		    	int headerTop = cursorGroupView.getTop();
		    	if (headerTop < mHeaderMeasuredHeight + dividerHeight) {
		    		mHeaderOffset = headerTop - (mHeaderMeasuredHeight + dividerHeight);
		    	}
		    	break;
		    }
	    }

	    invalidate();
	    requestLayout();
		
	}
}
